package cn.k7g.alloy.core.objectmapper;

import cn.k7g.alloy.annotation.TimeExtra;
import cn.k7g.alloy.utils.TimeUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.Data;

import java.io.IOException;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;


/**
 * 序列化时间扩展器
 * @author victor-wu
 * @date 2021/9/27 下午1:10
 */
public class TimeExtraSerializer extends JsonSerializer<Object> {
    private TimeExtra timeExtra;

    public TimeExtraSerializer(TimeExtra timeExtra) {
        this.timeExtra = timeExtra;
    }

    @Override
    public void serialize(Object v, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (v == null) {
            jsonGenerator.writeNull();
            return;
        }
        jsonGenerator.writeObject(v);
        String currentName = jsonGenerator.getOutputContext().getCurrentName() + "Extra";

        Extra extra = convert(v);

        jsonGenerator.writeObjectField(currentName, extra);
    }

    private Extra convert(Object v) {
        Extra extra = new Extra();
        if (v instanceof LocalDateTime) {
            extra.timestamp = new Timestamp(((LocalDateTime) v).toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
            fill(extra);
            return extra;
        }

        if (v instanceof Date) {
            extra.timestamp = new Timestamp(((Date) v).getTime());
            fill(extra);
            return extra;
        }

        if (v instanceof LocalDate) {
            extra.timestamp = new Timestamp(((LocalDate) v).atStartOfDay().toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
            fill(extra);
            return extra;
        }

        throw new RuntimeException("不支持的时间格式类型！");
    }

    private void fill(Extra extra) {
        if (timeExtra.ago()) {
            extra.ago = new Timestamp(System.currentTimeMillis() - extra.timestamp.get());
            extra.agoLabel = TimeUtil.getDurationLabel(extra.ago.get());
        }
    }

    @Data
    static class Extra implements Serializable {
        private Timestamp timestamp;
        private Timestamp ago;
        private String agoLabel;
    }
}
